/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once


#include <nmmintrin.h>
#include <immintrin.h>

#include <math.h>
#include <基本类型.h>
#include <几何数据.h>



// SSE系列指令集的支持级别. simd_sse_level 函数的返回值。
/*#define SIMD_SSE_NONE    0    // 不支持
#define SIMD_SSE_1    1    // SSE
#define SIMD_SSE_2    2    // SSE2
#define SIMD_SSE_3    3    // SSE3
#define SIMD_SSE_3S    4    // SSSE3
#define SIMD_SSE_41    5    // SSE4.1
#define SIMD_SSE_42    6    // SSE4.2

const char* simd_sse_names[] = {
	"None",
	"SSE",
	"SSE2",
	"SSE3",
	"SSSE3",
	"SSE4.1",
	"SSE4.2",
};


// 是否支持MMX指令集
BOOL    simd_mmx()
{
	const DWORD    BIT_DX_MMX = 0x00800000;    // bit 23
	DWORD    v_edx;

	// check processor support
	__try
	{
		_asm
		{
			mov eax, 1
			cpuid
			mov v_edx, edx
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		return FALSE;
	}
	if (v_edx & BIT_DX_MMX)
	{
		// check OS support
		__try
		{
			_asm
			{
				pxor mm0, mm0    // executing any MMX instruction
				emms
			}
			return TRUE;
		}
		__except (EXCEPTION_EXECUTE_HANDLER)
		{
		}
	}
	return FALSE;
}


// 检测SSE系列指令集的支持级别
int    simd_sse_level()
{
	const DWORD    BIT_D_SSE = 0x02000000;    // bit 25
	const DWORD    BIT_D_SSE2 = 0x04000000;    // bit 26
	const DWORD    BIT_C_SSE3 = 0x00000001;    // bit 0
	const DWORD    BIT_C_SSSE3 = 0x00000100;    // bit 9
	const DWORD    BIT_C_SSE41 = 0x00080000;    // bit 19
	const DWORD    BIT_C_SSE42 = 0x00100000;    // bit 20
	BYTE    rt = SIMD_SSE_NONE;    // result
	DWORD    v_edx;
	DWORD    v_ecx;

	// check processor support
	__try
	{
		_asm
		{
			mov eax, 1
			cpuid
			mov v_edx, edx
			mov v_ecx, ecx
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		return SIMD_SSE_NONE;
	}
	if (v_edx & BIT_D_SSE)
	{
		rt = SIMD_SSE_1;
		if (v_edx & BIT_D_SSE2)
		{
			rt = SIMD_SSE_2;
			if (v_ecx & BIT_C_SSE3)
			{
				rt = SIMD_SSE_3;
				if (v_ecx & BIT_C_SSSE3)
				{
					rt = SIMD_SSE_3S;
					if (v_ecx & BIT_C_SSE41)
					{
						rt = SIMD_SSE_41;
						if (v_ecx & BIT_C_SSE42)
						{
							rt = SIMD_SSE_42;
						}
					}
				}
			}
		}
	}

	// check OS support
	__try
	{
		_asm
		{
			xorps xmm0, xmm0    // executing any SSE instruction
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		return SIMD_SSE_NONE;
	}

	return rt;
}*/




/*CUDA_CALLABLE inline vec3 vec_add(vec3& a, const vec3& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, a.z, 0.0);
	__m128 a2 = _mm_set_ps(b.x, b.y, b.z, 0.0);
	
	__m128 寄存器结果A = _mm_add_ps(a1, a2);
	
	//float32 r[4];
	//_mm_storer_ps(r, 寄存器结果A);
	//return { r[0], r[1], r[2] };
	return { 寄存器结果A.m128_f32[3], 寄存器结果A.m128_f32[2], 寄存器结果A.m128_f32[1] };

}*/




/*inline vec3 operator+(const vec3& a, const float32& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, a.z, 0.0);
	__m128 a2 = _mm_set_ps(b, b, b, b);

	__m128 结果A = _mm_add_ps(a1, a2);

	return { 结果A.m128_f32[3], 结果A.m128_f32[2], 结果A.m128_f32[1] };
};*/

/*inline vec3 operator+(const vec3& a, const vec3& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, a.z, 0.0);
	__m128 a2 = _mm_set_ps(b.x, b.y, b.z, 0.0);

	__m128 结果A = _mm_add_ps(a1, a2);

	return { 结果A.m128_f32[3], 结果A.m128_f32[2], 结果A.m128_f32[1] };
};*/











/*inline vec2 operator-(const vec2& a, const float32& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, 0, 0.0);
	__m128 a2 = _mm_set_ps(b, b, 0, 0.0);

	__m128 结果A = _mm_sub_ps(a1, a2);

	return { 结果A.m128_f32[3], 结果A.m128_f32[2] };
};

inline vec2 operator-(const vec2& a, const vec2& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, 0, 0.0);
	__m128 a2 = _mm_set_ps(b.x, b.y, 0, 0.0);

	__m128 结果A = _mm_sub_ps(a1, a2);

	return { 结果A.m128_f32[3], 结果A.m128_f32[2] };
};*/



/*inline vec3 operator+(const uvec3& a, const vec3& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, a.z, 0.0);
	__m128 a2 = _mm_set_ps(b.x, b.y, b.z, 0.0);

	__m128 结果A = _mm_add_ps(a1, a2);

	return { 结果A.m128_f32[3], 结果A.m128_f32[2], 结果A.m128_f32[1] };
};*/


/*inline vec3 operator-(const uvec3& a, const float32 b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, a.z, 0.0);
	__m128 a2 = _mm_set_ps(b, b, b, 0.0);

	__m128 结果A = _mm_sub_ps(a1, a2);

	return { 结果A.m128_f32[3], 结果A.m128_f32[2], 结果A.m128_f32[1] };
};*/






/*inline vec3 operator*(const vec3& a, const vec3& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, a.z, 0.0);
	__m128 a2 = _mm_set_ps(b.x, b.y, b.z, 0.0);

	__m128 寄存器结果A = _mm_mul_ps(a1, a2);

	//float32 r[4];
	//_mm_storer_ps(r, 寄存器结果A);
	//return { r[0], r[1], r[2] };
	return { 寄存器结果A.m128_f32[3], 寄存器结果A.m128_f32[2], 寄存器结果A.m128_f32[1] };
};*/



/*inline vec4 operator*(const vec4& a, const float32& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, a.z, a.w);
	__m128 a2 = _mm_set_ps(b, b, b, b);

	__m128 结果A = _mm_mul_ps(a1, a2);

	return { 结果A.m128_f32[3], 结果A.m128_f32[2], 结果A.m128_f32[1], 结果A.m128_f32[0] };
};*/







/*inline void operator*=(vec3& a, const float32& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, a.z, 0.0);
	__m128 a2 = _mm_set_ps(b, b, b, 0.0);

	__m128 寄存器结果A = _mm_mul_ps(a1, a2);

	a.x = 寄存器结果A.m128_f32[3];
	a.y = 寄存器结果A.m128_f32[2];
	a.z = 寄存器结果A.m128_f32[1];
};*/

/*
inline vec3 operator*=(const vec3& a, const float32& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, a.z, 0.0);
	__m128 a2 = _mm_set_ps(b, b, b, 0.0);

	__m128 寄存器结果A = _mm_mul_ps(a1, a2);

	return { 寄存器结果A.m128_f32[3], 寄存器结果A.m128_f32[2], 寄存器结果A.m128_f32[1] };
};
*/




/*inline vec2 operator/(const vec2& a, const vec2& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, 0, 0.0);
	__m128 a2 = _mm_set_ps(b.x, b.y, 0, 0.0);

	__m128 结果A = _mm_div_ps(a1, a2);

	return { 结果A.m128_f32[3], 结果A.m128_f32[2] };
};

inline vec2 operator/(const vec2& a, const float32& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, 0, 0.0);
	__m128 a2 = _mm_set_ps(b, b, 0, 0.0);

	__m128 寄存器结果A = _mm_div_ps(a1, a2);

	return { 寄存器结果A.m128_f32[3], 寄存器结果A.m128_f32[2] };
};

inline vec3 operator/(const vec3& a, const float32& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, a.z, 0.0);
	__m128 a2 = _mm_set_ps(b, b, b, 0.0);

	__m128 寄存器结果A = _mm_div_ps(a1, a2);

	return { 寄存器结果A.m128_f32[3], 寄存器结果A.m128_f32[2], 寄存器结果A.m128_f32[1] };
};

inline vec3 operator/(const vec3& a, const vec3& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, a.z, 0.0);
	__m128 a2 = _mm_set_ps(b.x, b.y, b.z, 0.0);

	__m128 结果A = _mm_div_ps(a1, a2);

	return { 结果A.m128_f32[3], 结果A.m128_f32[2], 结果A.m128_f32[1] };
};

inline vec3 operator/(const vec3& a, const uvec3& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, a.z, 0.0);
	__m128 a2 = _mm_set_ps(b.x, b.y, b.z, 0.0);

	__m128 结果A = _mm_div_ps(a1, a2);

	return { 结果A.m128_f32[3], 结果A.m128_f32[2], 结果A.m128_f32[1] };
};*/

/*
inline vec4 operator / (const vec4& a, const uvec4& b) {
	return { a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w };
};
*/





/*inline vec3 vec_mul(vec3& a, vec3& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, a.z, 0.0);
	__m128 a2 = _mm_set_ps(b.x, b.y, b.z, 0.0);

	__m128 寄存器结果A = _mm_mul_ps(a1, a2);

	return { 寄存器结果A.m128_f32[3], 寄存器结果A.m128_f32[2], 寄存器结果A.m128_f32[1] };

}*/





/*inline float32 vec_len(const vec3& v) {
	__m128 a1 = _mm_set_ps(0.0f, v.z, v.y, v.x);
	__m128 a2 = _mm_set_ps(0.0f, v.z, v.y, v.x);

	__m128 寄存器结果A = _mm_mul_ps(a1, a2);
	_mm_sqrt_ps()
	//float32 r[4];
	//_mm_storer_ps(r, 寄存器结果A);
	//return { r[0], r[1], r[2] };
	return { 寄存器结果A.m128_f32[3], 寄存器结果A.m128_f32[2], 寄存器结果A.m128_f32[1] };
}*/









/*inline vec2 operator+(const vec2& a, const float32& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, 0.0f, 0.0f);
	__m128 a2 = _mm_set_ps(b, b, b, b);

	__m128 结果A = _mm_add_ps(a1, a2);

	return { 结果A.m128_f32[3], 结果A.m128_f32[2] };
};

inline vec2 operator+(const vec2& a, const vec2& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, 0.0f, 0.0f);
	__m128 a2 = _mm_set_ps(b.x, b.y, 0.0f, 0.0f);

	__m128 结果A = _mm_add_ps(a1, a2);

	return { 结果A.m128_f32[3], 结果A.m128_f32[2] };
};


inline vec2 operator-(const vec2& a, const float32& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, 0, 0);
	__m128 a2 = _mm_set_ps(b, b, b, b);

	__m128 结果A = _mm_sub_ps(a1, a2);

	return { 结果A.m128_f32[3], 结果A.m128_f32[2] };
};

inline vec2 operator-(const vec2& a, const vec2& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, 0, 0);
	__m128 a2 = _mm_set_ps(b.x, b.y, 0, 0);

	__m128 结果A = _mm_sub_ps(a1, a2);

	return { 结果A.m128_f32[3], 结果A.m128_f32[2] };
};

inline vec2 operator-(const vec2& a, const ivec2& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, 0, 0);
	__m128 a2 = _mm_set_ps(b.x, b.y, 0, 0);

	__m128 结果A = _mm_sub_ps(a1, a2);

	return { 结果A.m128_f32[3], 结果A.m128_f32[2] };
};





inline vec2 operator*(const vec2& a, const vec2& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, 0.0, 0.0);
	__m128 a2 = _mm_set_ps(b.x, b.y, 0.0, 0.0);

	__m128 寄存器结果A = _mm_mul_ps(a1, a2);
	//float32 r[4];
	//_mm_storer_ps(r, 寄存器结果A);
	//return { r[0], r[1], r[2] };
	return { 寄存器结果A.m128_f32[3], 寄存器结果A.m128_f32[2] };
};












//============================================== vec4 ======================================================

inline vec4 operator/(const vec4& a, const uvec4& b) {
	__m128 a1 = _mm_set_ps(a.x, a.y, a.z, a.w);
	__m128 a2 = _mm_set_ps(b.x, b.y, b.z, b.w);

	__m128 结果A = _mm_div_ps(a1, a2);

	return { 结果A.m128_f32[3], 结果A.m128_f32[2], 结果A.m128_f32[1], 结果A.m128_f32[0] };
};*/














